/*
 * salidaSala.cpp
 *
 *  Created on: 01/07/2014
 *      Author: nicolas
 */

#include "../interfaces/iBus.h"
#include "../interfaces/iPersona.h"
#include "../ipc/Semaforo.h"
#include "../comun/SalaDePersonas.h"
#include "../comun/ServidorIDs.h"
#include "../ipc/ColaMensajes.h"
#include "../defines.h"
#include <stdlib.h>
#include <syslog.h>
#include <stdio.h>
#include "../comun/iSemaforo.h"
#include "../comun/ServidorRemoto.h"
#include "../ipcRemoto/SemaforoRemoto.h"
#include "../comun/SalaRemota.h"

int verProximaPersona(iSemaforo* sem, SalaDePersonas* sala) {
	sem->wait();
	int id = sala->verProximaPersona();
	sem->signal();
	return id;
}

int sacarPersonas(int idPersona, iSemaforo* sem, SalaDePersonas* sala) {
	sem->wait();
	sala->sacarPersona(idPersona);
	int cant = sala->cantidadDePersonas();
	sem->signal();
	return cant;
}

int main(int argc, char **argv) {

	if (argc != 3) {
		//error
		exit(1);
	}

	int numeroSala = atoi(argv[1]);
	Tipos::LugarDeSala lugarSala = (Tipos::LugarDeSala) atoi(argv[2]);

	char encabezado[80];
	sprintf(encabezado, "salidaSala numero %i,lugar %i", numeroSala, lugarSala);

	openlog(encabezado, LOG_PID | LOG_CONS, LOG_LOCAL0);

	syslog(LOG_INFO, "Se inicio salidaSala con args: %s, %s", argv[1], argv[2]);

	ServidorRemoto rpc;
	int idSala = rpc.pedirIdSala(numeroSala, Tipos::TP_SALIDA, lugarSala);

	int lleno, semShmem;

	if (lugarSala == Tipos::LUGAR_ENTRADA) {

		lleno = ID_SEM_SALA_ENT_LLENO(numeroSala);
		semShmem = ID_MUTEX_SALA_ENT(numeroSala);

	} else {

		lleno = ID_SEM_SALA_ZOO_LLENO(numeroSala);
		semShmem = ID_MUTEX_SALA_ZOO(numeroSala);

	}

	int idBroker = rpc.idBrokerConectado();
	bool salir = false;

	iBus bus(numeroSala, idSala, lugarSala);
	iPersona persona(numeroSala, lugarSala);
	SalaRemota shmemSala(numeroSala, lugarSala, idSala, idBroker);
	iSemaforo* semLleno = new SemaforoRemoto(lleno, idSala, idBroker);
	iSemaforo* sem = new SemaforoRemoto(semShmem, idSala, idBroker);

	int idPersona, cantidad;

	while (!salir) {
		bus.recibirMensaje();
		syslog(LOG_INFO, "Recibio peticion del bus");
		idPersona = verProximaPersona(sem, &shmemSala);
		persona.permitirAscenso(idPersona);
		syslog(LOG_INFO, "Permite el ascenso de la peresona %i", idPersona);
		persona.recibirInformeAscenso();
		syslog(LOG_INFO, "Recibio informe de ascenso");
		cantidad = sacarPersonas(idPersona, sem, &shmemSala);
		bus.enviarRespuesta(idPersona);
		syslog(LOG_INFO, "Envio respuesta al bus");
		if (cantidad == CANTMAX - 1)
			semLleno->signal();
	}

}

